using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;
using AjaxPro;

internal class TagHandler : IHttpHandler
{
    private readonly IDictionary<String, Tag> tags;

    public TagHandler(IDictionary<String, Tag> tags)
    {
        this.tags = tags;
    }

    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.RequestType == "GET")
        {
            WriteTags(context);
        }
        else if (context.Request.RequestType == "POST")
        {
            PutTag(context);
        }
        else
        {
            throw new HttpException("Unexpected request!");
        }
    }

    public bool IsReusable
    {
        get { return true; }
    }

    private void WriteTags(HttpContext context)
    {
        JavaScriptObject jso = new JavaScriptObject();
        foreach (KeyValuePair<string, Tag> item in tags)
        {
            jso.Add(item.Key, item.Value.ToJavaScript());
        }
        WriteJson(context, jso);
    }

    private void PutTag(HttpContext context)
    {
        JavaScriptObject jso = ReadJson<JavaScriptObject>(context);
        Tag tag = new Tag(JavaScriptAs<String>(jso["description"]),
            DateTime.UtcNow);
        tags[JavaScriptAs<String>(jso["name"])] = tag;
        WriteJson(context, tag.ToJavaScript());
    }

    private static void WriteJson(HttpContext context, IJavaScriptObject js)
    {
        context.Response.ContentType = "application/json";
        context.Response.ContentEncoding = Encoding.UTF8;
        StringBuilder sb = new StringBuilder();
        JavaScriptSerializer.Serialize(js, sb);
        context.Response.Output.Write(sb);
    }

    private static T ReadJson<T>(HttpContext context)
        where T : IJavaScriptObject
    {
        if (context.Request.ContentType != "application/json")
        {
            throw new ArgumentException("Invalid content type! Expected: application/json");
        }
        using (StreamReader reader = new StreamReader(context.Request.InputStream, Encoding.UTF8))
        {
            return (T) JavaScriptDeserializer.DeserializeFromJson(reader.ReadToEnd(), typeof(T));
        }
    }

    private static T JavaScriptAs<T>(IJavaScriptObject js)
    {
        return (T) JavaScriptDeserializer.Deserialize(js, typeof (T));
    }
}